/* *****************************************************************************
Purpose: To read and convert a DataMAX Data File into a MATLAB readable file
         formatted for the Vibration data analysis structure.

Created: 28-Jan-2004

Author: Christopher McLeod
        Mantech International Corporation
	    Mail Code 540.5
		NASA / Goddard Space Flight Center
		Greenbelt, MD 20771

Modified:
		13-Apr-2004
		_v13
		Changed: (float *) malloc(GHeader.NumOfChannels * ChanLength * sizeof(float)
		To:      (float *) mxMalloc(GHeader.NumOfChannels * ChanLength * sizeof(float)
		16-Apr-2004
		_v15
		Changed: Project.Test_Item.Run.Time_Ref = (double *) malloc(ChanLength * sizeof(double))
		To:      Project.Test_Item.Run.Time_Ref = (double *) mxMalloc(ChanLength * sizeof(double))
		06-May-2004:
		_v17
		Added parsing of Comment field to extract
		Transducer Location; Trans Type; Cable Ext; Serial Num
		08-May-2004
		_v19
		Changed: Trans_Loc from 31 to 61 char wide
		_v20
		Change
			- Removed possible CR-LF from Note -> Run Description
		_v21
		Added default values for Orientation and Direction
		_v22
		Changed:     int delimiterPos[] = {0, 0, 0};
		To: unsigned int delimiterPos[] = {0, 0, 0};
		_v23
		Changed method of extracting the channel Coordinate, Direction, and Orientation. The new method
		should handle cases where the DataMAX Label parameter is not in the standard '100X+' format.
		The Coordinate can now be up to 18 characters long.
		The Direction can now be up to 9 characters long.
		_v24
		Same as _v23, but with some comments removed
		12-Nov-2005
		_v25
		Changed: Free(Project.Test_Item.Run.Time_Ref);
		To:      mxFree(Project.Test_Item.Run.Time_Ref);

******************************************************************************** */
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mex.h"

#pragma pack(2)

/* ***************************************************************************** */
/* ********************   Start of GLOBAL Declarations ************************* */
/* ***************************************************************************** */

/* * * * * * * * * * *  Declare GLOBAL constants   * * * * * * * * * * * * * * * */
#define MAX_NUM_BOARDS    24
#define MAX_DECIMAL_VALUE 32768.0
#define NUM_CHAN_FIELDS	(sizeof(Chan_field_names)/sizeof(*Chan_field_names))
#define NUM_CHAN_STRUCTS (sizeof(Project.Test_Item.Run.Channel)/sizeof(struct C_Struct))

/* * * * * * * * * *    Declare GLOBAL type definitions    * * * * * * * * * * * */
struct DisplayInfo {					/* <<< 72 Byte Structure >>> */
	unsigned long int	DisplayType;
	unsigned long int	D_BoardNum;
	unsigned long int	D_ChanNum;
	unsigned long int	D_BarBegin;
	unsigned long int	D_BarEnd;
	unsigned long int	D_Vertical;
	unsigned long int	D_Voltage;
	unsigned long int	D_GridEnable;
	unsigned long int	D_EngUnitEnable;
	unsigned long int	D_Color;
	char				Unused01[32];
};

struct GlobalHeader {					/* <<< 1904 Byte Header Record >>> */
	char				FileID[8];		/* Byte 0 */
	unsigned long int	Version;
	unsigned long int	NumOfBoards;
	unsigned long int	NumOfChannels;
	unsigned long int	NumOfSwipes;
	unsigned long int	NumOfDisplays;
	struct DisplayInfo	ChanDisplay[8];
	unsigned short int	Year;
	unsigned short int	Month;
	unsigned short int	Day;
	unsigned short int	Date;
	unsigned short int	Hour;
	unsigned short int	Minute;
	unsigned short int	Second;
	unsigned short int	MilliSecond;
	unsigned long int	NoteLength;
	char				UserNote[1024];
	char				Unused01[256];
} GHeader;

struct ChanStruc {
	unsigned long int	BoardNum;
	unsigned long int	ChannelNum;			/* 0 - 7 */
	unsigned long int	Bandwidth;
	unsigned long int	SampleRate;
	unsigned long int	Scalar;				/* 0 = 40V, 1 = 10V, 2 = 4V, 3 = 1V */
	float				Scale;
	char				Unit[8];
	char				Label[32];
	char				Comment[80];
	unsigned long int	EnableStatus;		/* 0 = Disable, 1 = Enable */
	float				EngUnitOffset;
	unsigned long int	PreTestZeroEnable;	/* 0 = Disable, 1 = Enable */
	float				PreTestZeroValue;
	char				Unused01[40];
};

struct Board {
	unsigned long int	SerialNum;
	unsigned long int	NumOfChannels;
	struct ChanStruc	Channel[8];
} BoardParam[MAX_NUM_BOARDS];

struct C_Struct {
	int		Module;
	int		ChanNbr;
	char	Trans_Loc[61];
	char	Coordinate[19];
	char	Direction[10];
	char	Orientation[2];
	double	Sensitivity;
	char	EU[6];
	char	Trans_Type[7];
	char	Cable_Ext[12];
	char	Serial_Num[17];
	char	Bypass[8];
	char	Coupling[9];
	double	Max_Volts;
	double	Max_EU;
	float	*Time_His;
};

struct R_Struct {
	char			Test_Date[11];
	char			Test_Type[12];
	char			Test_Level[15];
	char			Axis[3];
	double			*Time_Ref;
	int				Num_Chan;
	double			Sample_Rate;
	int				Low_Pass;
	char			Setup_File[20];
	char			ADF_File[23];
	struct C_Struct	Channel[192];
	char			Descrip[60];
};

struct T_Struct {
	char			Name[60];
	int				WD;
	struct R_Struct	Run;
};

struct P_Struct {
	char			Name[60];
	struct T_Struct	Test_Item;
} Project = {0};

/* * * * * * * * * * * *  Declare GLOBAL variables   * * * * * * * * * * * * * * * * * */
char			DM_FileName[150]		= {0};
FILE				*FilePtr;

const int			COUNT = 1;
const unsigned int	MUXFACTOR = 2;
float				*Channel_Time_History;
double				FullScale;
double				Volts;
int					BoardChans[MAX_NUM_BOARDS];
int					bfnIndex;
int					chanIndex;
int					chanIndexMod;
int					EnabledChans;
int					Index;
int					NewLoopStartValue;
int					NFrames;
int					rec_count;
short int			DecimalValue = 0;
unsigned long int	BChans;
unsigned long int	boardIndex;
unsigned long int	ChanNumIndex;
unsigned long int	ChanLength;
unsigned short int	DataValue;
unsigned long int	Offset;
unsigned long int	indexBChans;
unsigned short int	*SwipeFrame;

/* * * * * * * * * * * *  Declare Function Prototypes   * * * * * * * * * */
short int TwoComp_to_Decimal(unsigned short int DataValue);

void TrimString(char theString[]);

void ReadHeader(void);

void DisplayHeader(void);

void AssignProject(void);

void GetEnabled(void);

void CreateChannels(void);

void ReadData(void);

void ShowChannel(void);

void Read_DataMAX(char inBuff[]);

/* ********************   End of GLOBAL Declarations ************************* */

/* *************************************************************************** */
/* Function to convert 16 bit two's complement values to signed decimal values */
/* *************************************************************************** */
short int TwoComp_to_Decimal(unsigned short int DataValue)
{
	unsigned short int SignMask = 0X8000;

	if ((DataValue & SignMask) == SignMask)
		return(-1 * (~DataValue + 1));
	else
		return(DataValue);
}

/* *************************************************************************** */
/*         Trim the leading and trailing spaces from theString                 */
/* *************************************************************************** */
void TrimString(char theString[])
{
	int index		= 0;
	int first		= 0;
	int last		= 0;
	int length		= 0;
	int numchars	= 0;
	char tmpstr[60] = {0};

	length = strlen(theString);
	if ((theString[0] == ' ') || (theString[length - 1] == ' '))
	{
		while ((theString[index] == ' ') && (index < (length - 1)))
			index++;
		if (index == (length - 1)) /* The string consists of all spaces */
			theString[1] = '\0';
		else
		{
			first = index;
			index = length - 1;
			while (theString[index] == ' ')
				index--;
			last = index;
			numchars = (last - first + 1);
			strncpy(tmpstr, &theString[first], numchars);
			for (index = 0; index < length; index++)
				theString[index] = '\0';
			strncpy(theString, tmpstr, numchars);
		}
	} /* if ((theString[0] != ' ') && (theString[length - 1] != ' ')) */
	return;
}

/* *************************************************************************** */
/*  Open the file ans read the contents of the Global Header and the Board     */
/*  Parameter Header                                                           */
/* *************************************************************************** */
void ReadHeader(void)
{
	/* Open for read (will fail if file "data" does not exist) */
	if( (FilePtr  = fopen( DM_FileName, "r+b" )) == NULL )
		mexPrintf("The file %s was not opened.\n", DM_FileName);
	else
	{
		fseek(FilePtr, 0L, SEEK_SET);
		/* mexPrintf("The file %s was opened.\n", DM_FileName); */
		/*   ------------ Read the Global Header ------------   */
		rec_count = fread(&GHeader, sizeof(struct GlobalHeader), COUNT, FilePtr);
		for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++)
		{
			/*   ------------ Read the Board Parameters ------------   */
			rec_count = fread(&BoardParam[boardIndex], sizeof(struct Board), COUNT, FilePtr);
		}
	} /*  if( (FilePtr  = fopen( DM_FileName, "r+b" )) == NULL ) - else */
	if( fclose( FilePtr ) )
		mexPrintf("The file %s was not closed.\n", DM_FileName);
} /* End of ReadHeader */

/* *************************************************************************** */
/*  Display the contents of the Global Header and the Board Parameter Header   */
/* *************************************************************************** */
void DisplayHeader(void)
{
	/* unsigned long int index; */
	/* unsigned long int chan_index; */

	/*   ------------ Display Contents of the Global Header ------------   */
	mexPrintf("DataMAX Global Header Contents:\n");
	mexPrintf("File Identification ............. %s\n", GHeader.FileID);
	mexPrintf("Version ......................... %10u\n", GHeader.Version);
	mexPrintf("Number of Boards ................ %10u\n", GHeader.NumOfBoards);
	mexPrintf("Number of Channels .............. %10u\n", GHeader.NumOfChannels);
	mexPrintf("Number of 100 milliSec Swipes ... %10u\n", GHeader.NumOfSwipes);
	mexPrintf("Number of Displays .............. %10u\n", GHeader.NumOfDisplays);
	mexPrintf("Display Info Substructure:\n");
/* 11-Nov-2005
	for (index = 0; index < GHeader.NumOfDisplays; index++)
	{
		mexPrintf("\n--------------------------------------\n");
		mexPrintf("Display No. %2u:\n", index + 1);
		mexPrintf("Display Type .................... %10u\n", GHeader.ChanDisplay[index].DisplayType);
		mexPrintf("Board Number .................... %10u\n", GHeader.ChanDisplay[index].D_BoardNum);
		mexPrintf("Channel Number .................. %10u\n", GHeader.ChanDisplay[index].D_ChanNum);
		mexPrintf("Beginning Bar for Bar Display ... %10u\n", GHeader.ChanDisplay[index].D_BarBegin);
		mexPrintf("Ending Bar for Bar Display ...... %10u\n", GHeader.ChanDisplay[index].D_BarEnd);
		mexPrintf("Vertical Expansion Factor ....... %10u\n", GHeader.ChanDisplay[index].D_Vertical);
		mexPrintf("Voltage Offset .................. %10u\n", GHeader.ChanDisplay[index].D_Voltage);
		mexPrintf("Grid Enable Flag ................ %10u\n", GHeader.ChanDisplay[index].D_GridEnable);
		mexPrintf("Engineering Unit Enable ......... %10u\n", GHeader.ChanDisplay[index].D_EngUnitEnable);
		mexPrintf("Color of Display ................ %10u\n", GHeader.ChanDisplay[index].D_Color);
	}
11-Nov-2005 */
 /* for (int index = 0; index < GHeader.NumOfDisplays; index++) */

	mexPrintf("\n--------------------------------------\n");
	mexPrintf("Year ............................ %10u\n", GHeader.Year);
	mexPrintf("Month ........................... %10u\n", GHeader.Month);
	mexPrintf("Day ............................. %10u\n", GHeader.Day);
	mexPrintf("Date ............................ %10u\n", GHeader.Date);
	mexPrintf("Hour ............................ %10u\n", GHeader.Hour);
	mexPrintf("Minute .......................... %10u\n", GHeader.Minute);
	mexPrintf("Second .......................... %10u\n", GHeader.Second);
	mexPrintf("MilliSecond ..................... %10u\n", GHeader.MilliSecond);
	mexPrintf("Number of characters for Note ... %10u\n", GHeader.NoteLength);
	/* mexPrintf("User Note ....................... %1024s\n", GHeader.UserNote); */

	/*   ------------ Display Contents of the Board Parameter ------------   */
/* 17-May-2006 Chris McLeod
	for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++)
	{
		mexPrintf("\n--------------------------------------\n");
		mexPrintf("Board No. %1i\n", boardIndex+1);
		mexPrintf("Board Serial No. ................ %10u\n", BoardParam[boardIndex].SerialNum);
		mexPrintf("Number of Channels .............. %10u\n", BoardParam[boardIndex].NumOfChannels);

		for (chan_index = 0; chan_index < BoardParam[boardIndex].NumOfChannels; chan_index++)
		{
			mexPrintf("\n-------------\n");
			mexPrintf("Board Number .................... %10u\n", BoardParam[boardIndex].Channel[chan_index].BoardNum);
			mexPrintf("Channel Number .................. %10u\n", BoardParam[boardIndex].Channel[chan_index].ChannelNum);
			mexPrintf("Channel Bandwidth ............... %10u\n", BoardParam[boardIndex].Channel[chan_index].Bandwidth);
			mexPrintf("Channel Sample Rate ............. %10u\n", BoardParam[boardIndex].Channel[chan_index].SampleRate);
			mexPrintf("Channel Scalar .................. %10u\n", BoardParam[boardIndex].Channel[chan_index].Scalar);
			mexPrintf("Channel Scale ................... %10u\n", BoardParam[boardIndex].Channel[chan_index].Scale);
			mexPrintf("Channel Unit .................... %8s\n",  BoardParam[boardIndex].Channel[chan_index].Unit);
			mexPrintf("Channel Label ................... %32s\n", BoardParam[boardIndex].Channel[chan_index].Label);
			mexPrintf("Comment ......................... %80s\n", BoardParam[boardIndex].Channel[chan_index].Comment);
			mexPrintf("Channel Enable Status ........... %10u\n", BoardParam[boardIndex].Channel[chan_index].EnableStatus);
			mexPrintf("Channel Engineering Unit Offset . %10.5f\n", BoardParam[boardIndex].Channel[chan_index].EngUnitOffset);
			mexPrintf("Channel Pre-Test Zero Enable .... %10u\n", BoardParam[boardIndex].Channel[chan_index].PreTestZeroEnable);
			mexPrintf("Channel Pre-Test Zero Value ..... %10.5f\n", BoardParam[boardIndex].Channel[chan_index].PreTestZeroValue);
		}
	}
17-May-2006 */
	 /* for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++) */
} /* end of DisplayHeader */

/* *************************************************************************** */
/*  Assign the DataMAX parameters to the Project structure.                    */
/* *************************************************************************** */
void AssignProject(void)
{
	char sYear[5];
	char sMonth[3];
	char sDate[12];
	const char DELIMITER = ';';
	const char *Months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
		                    "Sep", "Oct", "Nov", "Dec"};
	double Points;
	double index;
	double Time_Inc;
	int delimiterIndex;
	int DescripIndex;
	int DescripLen;
	int iIndex;
	int len;
	int sublen;
	int substart;
	int TR_Index;
	unsigned int delimiterPos[] = {0, 0, 0};
	unsigned int strIndex;

	/* Assign default Project.Name */
	strcpy(Project.Name, "XYZ Project");

	/* Assign default Project.Test_Item.Name */
	strcpy(Project.Test_Item.Name, "Test Item Name");

	/* Assign default WD */
	Project.Test_Item.WD = 1234;

	/* Assign Project.Test_Item.Run.Test_Date */
	_itoa(GHeader.Date, sDate, 10);		/* Convert the integer to a string */
	strcpy(sMonth, Months[GHeader.Month - 1]);
	_itoa(GHeader.Year, sYear, 10);		/* Convert the integer to a string */
	strcat(sDate,"-");
	strcat(sDate, sMonth);
	strcat(sDate, "-");
	strcat(sDate, sYear);
	strcpy(Project.Test_Item.Run.Test_Date, sDate);

	/* Assign default Project.Test_Item.Run.Test_Level */
	strcpy(Project.Test_Item.Run.Test_Level, "    ");

	/* Assign Project.Test_Item.Run.Setup_File */
	strcpy(Project.Test_Item.Run.Setup_File, "    ");

	/* Assign Project.Test_Item.Run.Axis */
	switch (Project.Test_Item.Run.Setup_File[0])
	{
		case 'X':
		case 'x':
		case 'Y':
		case 'y':
		case 'Z':
		case 'z':
			strncpy(Project.Test_Item.Run.Axis, Project.Test_Item.Run.Setup_File, 1);
			break;
		default:
			strcpy(Project.Test_Item.Run.Axis, " ");
	}

	/* ************************************************************* */
	/*    Allocate memory for the Time_Ref buffer                    */
	/*    Generate a Time Reference                                  */
	/* ************************************************************* */
	ChanLength = (int)(BoardParam[0].Channel[0].SampleRate * 0.1 * GHeader.NumOfSwipes);
	if ((Project.Test_Item.Run.Time_Ref = (double *) mxMalloc(ChanLength * sizeof(double))) == NULL)
		mexPrintf("Memory allocation for Project.Test_Item.Run.Time_Ref FAILED!\n");
	else
	{
		/* mexPrintf("Memory allocation for Project.Test_Item.Run.Time_Ref Complete.\n"); */
		Time_Inc = 1.0 / (double) BoardParam[0].Channel[0].SampleRate;
		Points = (double) ChanLength;
		TR_Index = 0;
		for (index = 0.0; index < Points; index++)
		{
			*(Project.Test_Item.Run.Time_Ref + TR_Index) = Time_Inc * index;;
			TR_Index++;
		}
	}
    GetEnabled();
	/* Assign Number of Channels */
	Project.Test_Item.Run.Num_Chan = GHeader.NumOfChannels;
	/*	mexPrintf ("Project.Test_Item.Run.Num_Chan = %u\n", Project.Test_Item.Run.Num_Chan); */

	/* Assign the Sample Rate */
	Project.Test_Item.Run.Sample_Rate = (double) BoardParam[0].Channel[0].SampleRate;
	/*	mexPrintf("Project.Test_Item.Run.Sample_Rate = %f\n", Project.Test_Item.Run.Sample_Rate); */

	/* Assign the Low Pass Frequency */
	Project.Test_Item.Run.Low_Pass = BoardParam[0].Channel[0].Bandwidth;
	/*	mexPrintf("Project.Test_Item.Run.Low_Pass = %i\n", Project.Test_Item.Run.Low_Pass); */

	/* Assign Project.Test_Item.Run.ADF_File */
	strcpy(Project.Test_Item.Run.ADF_File, "   ");
	/*	mexPrintf("Project.Test_Item.Run.ADF_File = %s\n", Project.Test_Item.Run.ADF_File); */
	
	/* Assign the Run Description field */
	strncpy(Project.Test_Item.Run.Descrip, GHeader.UserNote, 59);
	DescripLen = strlen(Project.Test_Item.Run.Descrip);
	for (DescripIndex = (DescripLen - 1); Project.Test_Item.Run.Descrip[DescripIndex] < 33; DescripIndex--)	{ } /* Remove possible [CR-LF] */
	Project.Test_Item.Run.Descrip[DescripIndex + 1] = '\0';
	/* mexPrintf("Project.Test_Item.Run.Descrip = %s <\n", Project.Test_Item.Run.Descrip); */

	/* Assign Project.Test_Item.Run.Channel.Module */
	/*	Project.Test_Item.Run.Channel[0].Module = 1;
	mexPrintf("Project.Test_Item.Run.Channel[0].Module = %i\n", Project.Test_Item.Run.Channel[0].Module); */

	/* Assign indivdual channel parameters */
	for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++)
	{
		for (chanIndex = 0; chanIndex < 8; chanIndex++)
		{
			ChanNumIndex = boardIndex * 8 + chanIndex;
			Project.Test_Item.Run.Channel[ChanNumIndex].Module = boardIndex;
			Project.Test_Item.Run.Channel[ChanNumIndex].ChanNbr = ChanNumIndex + 1;

			/* Locate the delimiters */
			delimiterIndex = 0;
			for (strIndex = 0; strIndex < strlen(BoardParam[boardIndex].Channel[chanIndex].Comment); strIndex++)
				if (BoardParam[boardIndex].Channel[chanIndex].Comment[strIndex] == DELIMITER)
				{
					delimiterPos[delimiterIndex] = strIndex;
					delimiterIndex++;
				}

			/* Assign Transducer Location */
			substart = 0;
			sublen = delimiterPos[0] - substart;
			iIndex = 0;
			for (strIndex = substart; strIndex < delimiterPos[0]; strIndex++)
			{
				Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Loc[iIndex] = BoardParam[boardIndex].Channel[chanIndex].Comment[strIndex];
				iIndex++;
			}
			Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Loc[iIndex] = '\0';
			TrimString(Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Loc);

			/* Assign Transducer Type */
			substart = delimiterPos[0] + 1;
			sublen = delimiterPos[1] - substart;
			iIndex = 0;
			for (strIndex = substart; strIndex < delimiterPos[1]; strIndex++)
			{
				Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Type[iIndex] = BoardParam[boardIndex].Channel[chanIndex].Comment[strIndex];
				iIndex++;
			}
			Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Type[iIndex] = '\0';
			TrimString(Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Type);

			/* Assign Cable_Ext */
			substart = delimiterPos[1] + 1;
			sublen = delimiterPos[2] - substart;
			iIndex = 0;
			for (strIndex = substart; strIndex < delimiterPos[2]; strIndex++)
			{
				Project.Test_Item.Run.Channel[ChanNumIndex].Cable_Ext[iIndex] = BoardParam[boardIndex].Channel[chanIndex].Comment[strIndex];
				iIndex++;
			}
			Project.Test_Item.Run.Channel[ChanNumIndex].Cable_Ext[iIndex] = '\0';
			TrimString(Project.Test_Item.Run.Channel[ChanNumIndex].Cable_Ext);
			
			/* Assign Serial_Num */
			substart = delimiterPos[2] + 1;
			sublen = strlen(BoardParam[boardIndex].Channel[chanIndex].Comment) - substart;
			iIndex = 0;
			for (strIndex = substart; strIndex < strlen(BoardParam[boardIndex].Channel[chanIndex].Comment); strIndex++)
			{
				Project.Test_Item.Run.Channel[ChanNumIndex].Serial_Num[iIndex] = BoardParam[boardIndex].Channel[chanIndex].Comment[strIndex];
				iIndex++;
			}
			Project.Test_Item.Run.Channel[ChanNumIndex].Serial_Num[iIndex] = '\0';
			TrimString(Project.Test_Item.Run.Channel[ChanNumIndex].Serial_Num);

			/* Assign Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate  */
			/*        Project.Test_Item.Run.Channel[ChanNumIndex].Direction   */
			/*        Project.Test_Item.Run.Channel[ChanNumIndex].Orientation */
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate, "                  ");
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Direction, "         ");
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Orientation, " ");
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate, BoardParam[boardIndex].Channel[chanIndex].Label);
			TrimString(Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate);
			len = strlen(Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate);
			for (iIndex = 0; (iIndex < len) &&
				 ((Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate[iIndex] > 47) &&
				  (Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate[iIndex] < 58)); iIndex++) { }

			strncpy(Project.Test_Item.Run.Channel[ChanNumIndex].Direction, &Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate[iIndex], len - iIndex);
			Project.Test_Item.Run.Channel[ChanNumIndex].Coordinate[iIndex] = '\0';

			TrimString(Project.Test_Item.Run.Channel[ChanNumIndex].Direction);
			len = strlen(Project.Test_Item.Run.Channel[ChanNumIndex].Direction);

			if ((Project.Test_Item.Run.Channel[ChanNumIndex].Direction[len - 1] == '+') ||
				(Project.Test_Item.Run.Channel[ChanNumIndex].Direction[len - 1] == '-'))
			{
				Project.Test_Item.Run.Channel[ChanNumIndex].Orientation[0] = Project.Test_Item.Run.Channel[ChanNumIndex].Direction[len - 1];
				Project.Test_Item.Run.Channel[ChanNumIndex].Orientation[1] = '\0';
				Project.Test_Item.Run.Channel[ChanNumIndex].Direction[len - 1] = '\0';
			}
			else
				Project.Test_Item.Run.Channel[ChanNumIndex].Orientation[0] = '\0';

			Project.Test_Item.Run.Channel[ChanNumIndex].Sensitivity = (double) BoardParam[boardIndex].Channel[chanIndex].Scale;
			strncpy(Project.Test_Item.Run.Channel[ChanNumIndex].EU, BoardParam[boardIndex].Channel[chanIndex].Unit, 5);
			/*
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Trans_Type, "   ");
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Cable_Ext, "   ");
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Serial_Num, "   ");
			*/
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Bypass, "Off");
			strcpy(Project.Test_Item.Run.Channel[ChanNumIndex].Coupling, "DC");

			switch (BoardParam[boardIndex].Channel[chanIndex].Scalar)
			{
				case 0: { FullScale = 40.0; break; }
				case 1: { FullScale = 10.0; break; }
				case 2: { FullScale = 4.0; break; }
				case 3: { FullScale = 1.0; break; }
				default: mexPrintf("Incorrect FullScale Value.\n");
			}
			Project.Test_Item.Run.Channel[ChanNumIndex].Max_Volts = FullScale;
			Project.Test_Item.Run.Channel[ChanNumIndex].Max_EU = 5.0; /* A meaningless dummy value */

		} /* for (chanIndex = 0; chanIndex < 8; chanIndex++) */
	} /* for (boardIndex = 0; boardIndex < NumOfBoards; boardIndex++) */
} /* End of AssignProject */

/* *************************************************************************** */
/*    Determine the number of enabled channels on each board                   */
/* *************************************************************************** */
void GetEnabled(void)
{
	/* mexPrintf("\n--------------------------\n"); */
	/* mexPrintf("Determine the number of enabled channels.\n"); */
	EnabledChans = 0;
	for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++)
	{
		BoardChans[boardIndex] = 0;
		for (chanIndex = 0; chanIndex < 8; chanIndex++)
		{
			ChanNumIndex = boardIndex * 8 + chanIndex;
			if (BoardParam[boardIndex].Channel[chanIndex].EnableStatus == 1)
				BoardChans[boardIndex] = BoardChans[boardIndex] + 1;
		}
		EnabledChans += BoardChans[boardIndex];
	} /* for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++) */
	/* Locate the last enabled board */
	boardIndex = GHeader.NumOfBoards - 1;
	while (BoardChans[boardIndex] == 0)
		boardIndex--;
	/* Locate the last enabled channel on the last enabled board */
	chanIndex = 7;
	while(BoardParam[boardIndex].Channel[chanIndex].EnableStatus == 0)
		chanIndex--;
	GHeader.NumOfBoards = boardIndex + 1;
	GHeader.NumOfChannels = (boardIndex + 1) * 8;
    /*
	mexPrintf("\nFunction GetEnabled: \n");
	mexPrintf("boardIndex ...................... %u \n", boardIndex);
	mexPrintf("Number of Boards ................ %10u\n", GHeader.NumOfBoards);
	mexPrintf("Number of Channels .............. %10u\n\n", GHeader.NumOfChannels);
    */
} /* End of GetEnabled */

/* *************************************************************************** */
/* Dyamically allocate the channels to be used for the time history data       */
/* *************************************************************************** */
void CreateChannels(void)
{
	unsigned long int	NumBytes;
	NFrames = (int)(BoardParam[0].Channel[0].SampleRate * 0.1);
	ChanLength = NFrames* GHeader.NumOfSwipes;
	NumBytes = GHeader.NumOfChannels * ChanLength * sizeof(float);
	if ((Channel_Time_History = (float *) mxMalloc(GHeader.NumOfChannels * ChanLength * sizeof(float))) == NULL)
		mexPrintf("\nMemory allocation for Channel_Time_History FAILED!\n");
	/* else
		 mexPrintf("\nMemory allocation for Channel_Time_History COMPLETED!\n"); */
} /* End of createChannels */

/* *************************************************************************** */
/*  Read the data one swipe at a time, convert to volts and copy to the memory */
/*  space allocated in the function CreateChannels.                            */
/* *************************************************************************** */
void ReadData(void)
{
	unsigned long int	swipeIndex;

	/* Determine the number of enabled channels */
	/* GetEnabled(); */
	/* mexPrintf("\nEnabledChans = %i\n\n", EnabledChans); */
	/* Allocate memory for the channel arrays to be used for the time history data */
	CreateChannels();
	
	/* Dynamically allocate the Swipe Frame */
	if ((SwipeFrame = (unsigned short int *) malloc(EnabledChans * NFrames* sizeof(unsigned short int))) == NULL)
		mexPrintf("\nMemory allocation for SwipeFrame FAILED!\n");
	else
	{
		/* mexPrintf("\nMemory allocation for SwipeFrame COMPLETED!\n"); */

		/* Initialize indices */
		ChanNumIndex = 0;
		Index = 0; /* Array index for Channel_Time_History */
		/* Open for read (will fail if file "data" does not exist) */
		if( (FilePtr  = fopen( DM_FileName, "r+b" )) == NULL )
			mexPrintf("The file %s was not opened.\n", DM_FileName);
		else
		{
			/* Reset the file pointer to the start of the data */
			fseek(FilePtr, 65536L, SEEK_SET);
	
			/* The Number of Swipes is read from the Global Header */
	 		for (swipeIndex = 0; swipeIndex < GHeader.NumOfSwipes; swipeIndex++)
			{
				/* Read a SwipeFrame */
				fread(SwipeFrame, sizeof(unsigned short int), EnabledChans * NFrames, FilePtr);
				for (boardIndex = 0; boardIndex < GHeader.NumOfBoards; boardIndex++)
				{
					chanIndexMod = -1;
					NewLoopStartValue = Index;
					for (chanIndex = 0; chanIndex < 8; chanIndex++)
					{
						ChanNumIndex = boardIndex * 8 + chanIndex;
						Index = NewLoopStartValue;
						for (bfnIndex = 0; bfnIndex < NFrames; bfnIndex++)
						{
							if (BoardParam[boardIndex].Channel[chanIndex].EnableStatus == 1)
							{
								if (bfnIndex == 0) chanIndexMod++;
								switch (BoardParam[boardIndex].Channel[chanIndex].Scalar)
								{
									case 0: { FullScale = 40.0; break; }
									case 1: { FullScale = 10.0; break; }
									case 2: { FullScale = 4.0; break; }
									case 3: { FullScale = 1.0; break; }
									default: mexPrintf("Incorrect FullScale Value.\n");
								}

								BChans = 0;
								for (indexBChans = 0; indexBChans < boardIndex; indexBChans++)
									BChans += BoardChans[indexBChans];
								Offset = (NFrames * BChans) + (bfnIndex * BoardChans[boardIndex]) + chanIndexMod;
								DataValue = *(SwipeFrame + Offset);
								DecimalValue = TwoComp_to_Decimal(DataValue);
								Volts = (FullScale * (float)DecimalValue / MAX_DECIMAL_VALUE) - BoardParam[boardIndex].Channel[chanIndex].PreTestZeroValue;
								*(Channel_Time_History + ChanNumIndex * ChanLength + Index) =
								                      Volts * Project.Test_Item.Run.Channel[ChanNumIndex].Sensitivity;
								Index++;
							}
							else /* The channel has been disabled */
							{
								/* Write zeros to the time history */
								*(Channel_Time_History + ChanNumIndex * ChanLength + Index) = 0.0; /* Or the count value equivalent to zero */
								Index++;
							}
						} /* for (bfnIndex = 0; bfnIndex < N; bfnIndex++) */
					} /* for (chanIndex = 0; chanIndex < 8; chanIndex++) */
					Index = NewLoopStartValue;
				} /* for (boardIndex = 0; boardIndex < NumOfBoards; boardIndex++) */
				Index += NFrames;
			} /* for (swipeIndex = 0; swipeIndex < NumOfSwipes; swipeIndex++) */

		} /*  if( (FilePtr  = fopen( DM_FileName, "r+b" )) == NULL ) - else */
	} /* if ((SwipeFrame = (unsigned short int *) ... else */


	if( fclose( FilePtr ) )
		mexPrintf("The file %s was not closed.\n", DM_FileName);
} /* End of ReadData */

/* *************************************************************************** */
/*       Display a single channel of data.                                     */
/* *************************************************************************** */
void ShowChannel(unsigned long int	ChanNumIndex)
{
	mexPrintf("------------------------\n");
	for (Index = 0; Index < 20; Index++)
		mexPrintf("Chan[%2i][%3i] = %7.2f\n", ChanNumIndex, Index, *(Channel_Time_History + ChanNumIndex * ChanLength + Index));
} /* End of ShowChannel */

/* *************************************************************************** */
/*  The C language interface to the mexFunction                                */
/* *************************************************************************** */
void Read_DataMAX(char inBuff[])
{
	strcpy(DM_FileName, inBuff);

	ReadHeader();
	/* DisplayHeader(); */
	AssignProject();
	ReadData();
	/*	ShowChannel(0); */
} /* End of Read_DataMAX */

/* ****************************************************************************
 * Gateway function: mexFunction                                              *
 * Provide an interface between the computational "C" language functions,     *
 * read_prn, read_vdf, and MATLAB.                                            *
 ****************************************************************************** */
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
	const char *Chan_field_names[] = {"Module", "ChanNbr", "Trans_Loc", "Coordinate", "Direction", "Orientation",
									  "Sensitivity", "EU", "Trans_Type", "Cable_Ext", "Serial_Num", "Bypass",
									  "Coupling", "Max_Volts", "Max_EU", "Time_His"};

	const char *Run_field_names[] = {"Test_Date", "Test_Type", "Test_Level", "Axis", "Time_Ref", "Num_Chan",
									 "Sample_Rate", "Low_Pass", "Setup_File", "ADF_File", "Channel", "Descrip"};

	const char *TestItem_field_names[] = {"TI_Name", "WD", "Run"};

	const char *Project_field_names[] = {"Name", "Test_Item"};

	int dims[2] = {1, NUM_CHAN_STRUCTS};

	int Name_field, Test_Item_field;

	int TI_Name_field, WD_field, Run_field;

	int Test_Date_field, Test_Type_field, Test_Level_field, Axis_field, Time_Ref_field, Num_Chan_field,
		Sample_Rate_field, Low_Pass_field, Setup_File_field, ADF_File_field, Channel_field, Descrip_field;

	int Module_field, ChanNbr_field, Trans_Loc_field, Coordinate_field, Direction_field, Orientation_field,
		Sensitivity_field, EU_field, Trans_Type_field, Cable_Ext_field, Serial_Num_field, Bypass_field,
		Coupling_field, Max_Volts_field, Max_EU_field, Time_His_field;

	int index;

	mxArray *ChanStruct;
	mxArray *RunStruct;
	mxArray *TestItemStruct;

	/* Error checking for proper number of input & output arguments */
	/*
	mexPrintf("nrhs .................. %i\n", nrhs);
	mexPrintf("lrhs .................. %i\n", nlhs);
	*/
	/* ******************************************************************** */
	/*       Create a 1-by-n array of structures for the channel data       */
	/* ******************************************************************** */
	ChanStruct = mxCreateStructArray(2, dims, NUM_CHAN_FIELDS, Chan_field_names);

	/* ******************************************************************** */
	/*           Create a 1-by-1 struct matrix for the Run data             */
	/* ******************************************************************** */
	RunStruct = mxCreateStructMatrix(1, 1, 12, Run_field_names);

	/* ******************************************************************** */
	/*       Create a 1-by-1 struct matrix for the Test_Item data           */
	/* ******************************************************************** */
	TestItemStruct = mxCreateStructMatrix(1, 1, 3, TestItem_field_names);

	/* ******************************************************************** */
	/*        Create a 1-by-1 struct matrix for the Project data            */
	/* ******************************************************************** */
	plhs[0] = mxCreateStructMatrix(1, 1, 2, Project_field_names);

	/* ******************************************************************** */
	/*          Get the field numbers for each structure field              */
	/* ******************************************************************** */
	/*                   Project field numbers:                             */
	/* ******************************************************************** */
	Name_field     = mxGetFieldNumber(plhs[0], "Name");
	Test_Item_field = mxGetFieldNumber(plhs[0], "Test_Item");
	/*
	mexPrintf("\nProject field numbers:\n");
	mexPrintf("Name_field ............ %i\n", Name_field);
	mexPrintf("Test_Item_field ........ %i\n", Test_Item_field);
	*/
	/* ******************************************************************** */
	/*                 Test_Item field numbers:                             */
	/* ******************************************************************** */
	TI_Name_field = mxGetFieldNumber(TestItemStruct, "TI_Name");
	WD_field      = mxGetFieldNumber(TestItemStruct, "WD");
	Run_field     = mxGetFieldNumber(TestItemStruct, "Run");
	/*
	mexPrintf("\nTest_Item field numbers:\n");
	mexPrintf("TI_Name_field ......... %i\n", TI_Name_field);
	mexPrintf("WD_field .............. %i\n", WD_field);
	mexPrintf("Run_field ............. %i\n", Run_field);
	*/
	/* ******************************************************************** */
	/*                    Run field numbers:                                */
	/* ******************************************************************** */
	Test_Date_field   = mxGetFieldNumber(RunStruct, "Test_Date");
	Test_Type_field   = mxGetFieldNumber(RunStruct, "Test_Type");
	Test_Level_field  = mxGetFieldNumber(RunStruct, "Test_Level");
	Axis_field        = mxGetFieldNumber(RunStruct, "Axis");
	Time_Ref_field    = mxGetFieldNumber(RunStruct, "Time_Ref");
	Num_Chan_field    = mxGetFieldNumber(RunStruct, "Num_Chan");
	Sample_Rate_field = mxGetFieldNumber(RunStruct, "Sample_Rate");
	Low_Pass_field    = mxGetFieldNumber(RunStruct, "Low_Pass");
	Setup_File_field  = mxGetFieldNumber(RunStruct, "Setup_File");
	ADF_File_field    = mxGetFieldNumber(RunStruct, "ADF_File");
	Channel_field     = mxGetFieldNumber(RunStruct, "Channel");
	Descrip_field     = mxGetFieldNumber(RunStruct, "Descrip");
	/*
	mexPrintf("\nRun field numbers:\n");
	mexPrintf("Test_Date_field ....... %i\n", Test_Date_field);
	mexPrintf("Test_Type_field ....... %i\n", Test_Type_field);
	mexPrintf("Test_Level_field ...... %i\n", Test_Level_field);
	mexPrintf("Axis_field ............ %i\n", Axis_field);
	mexPrintf("Time_Ref_field ........ %i\n", Time_Ref_field);
	mexPrintf("Num_Chan_field ........ %i\n", Num_Chan_field);
	mexPrintf("Sample_Rate_field ..... %i\n", Sample_Rate_field);
	mexPrintf("Low_Pass_field ........ %i\n", Low_Pass_field);
	mexPrintf("Setup_File_field ...... %i\n", Setup_File_field);
	mexPrintf("ADF_File_field ........ %i\n", ADF_File_field);
	mexPrintf("Channel_field ......... %i\n", Channel_field);
	mexPrintf("Descrip_field ......... %i\n", Descrip_field);
	*/
	/* ******************************************************************** */
	/*                     Chan field numbers:                              */
	/* ******************************************************************** */
	Module_field      = mxGetFieldNumber(ChanStruct, "Module");
	ChanNbr_field     = mxGetFieldNumber(ChanStruct, "ChanNbr");
	Trans_Loc_field   = mxGetFieldNumber(ChanStruct, "Trans_Loc");
	Coordinate_field  = mxGetFieldNumber(ChanStruct, "Coordinate");
	Direction_field   = mxGetFieldNumber(ChanStruct, "Direction");
	Orientation_field = mxGetFieldNumber(ChanStruct, "Orientation");
	Sensitivity_field = mxGetFieldNumber(ChanStruct, "Sensitivity");
	EU_field          = mxGetFieldNumber(ChanStruct, "EU");
	Trans_Type_field  = mxGetFieldNumber(ChanStruct, "Trans_Type");
	Cable_Ext_field   = mxGetFieldNumber(ChanStruct, "Cable_Ext");
	Serial_Num_field  = mxGetFieldNumber(ChanStruct, "Serial_Num");
	Bypass_field      = mxGetFieldNumber(ChanStruct, "Bypass");
	Coupling_field    = mxGetFieldNumber(ChanStruct, "Coupling");
	Max_Volts_field   = mxGetFieldNumber(ChanStruct, "Max_Volts");
	Max_EU_field      = mxGetFieldNumber(ChanStruct, "Max_EU");
	Time_His_field    = mxGetFieldNumber(ChanStruct, "Time_His");
	/*
	mexPrintf("\nChan field numbers:\n");
	mexPrintf("Module_field .......... %i\n", Module_field);
	mexPrintf("ChanNbr_field ......... %i\n", ChanNbr_field);
	mexPrintf("Trans_Loc_field ....... %i\n", Trans_Loc_field);
	mexPrintf("Coordinate_field ...... %i\n", Coordinate_field);
	mexPrintf("Direction_field ....... %i\n", Direction_field);
	mexPrintf("Orientation_field ..... %i\n", Orientation_field);
	mexPrintf("Sensitivity_field ..... %i\n", Sensitivity_field);
	mexPrintf("EU_field .............. %i\n", EU_field);
	mexPrintf("Trans_Type_field ...... %i\n", Trans_Type_field);
	mexPrintf("Cable_Ext_field ....... %i\n", Cable_Ext_field);
	mexPrintf("Serial_Num_field ...... %i\n", Serial_Num_field);
	mexPrintf("Bypass_field .......... %i\n", Bypass_field);
	mexPrintf("Coupling_field ........ %i\n", Coupling_field);
	mexPrintf("Max_Volts_field ....... %i\n", Max_Volts_field);
	mexPrintf("Max_EU_field .......... %i\n", Max_EU_field);
	mexPrintf("Time_His_field ........ %i\n", Time_His_field);
	*/
	/* ******************************************************************* */
	/* Populate the "C"-structure by calling the computational functions   */
	/* read_prn & read_vdf                                                 */
	/* ******************************************************************* */
	{
	    char	*input_buf;
	    int		buflen, status;
		int		bytes_to_copy;
		unsigned char *Ptr;

		mxArray	*Low_Pass_field_value;
		mxArray *Sample_Rate_field_value;
		mxArray *Num_Chan_field_value;
		mxArray *Time_Ref_field_value;
		mxArray	*WD_field_value;

		/* ************************************************************ */
	    /*    Check for proper number of arguments                      */
		/* ************************************************************ */
	    if(nrhs!=1) 
	      mexErrMsgTxt("One input required.");
	    else if(nlhs > 1) 
	      mexErrMsgTxt("Too many output arguments.");

		/* ************************************************************ */
	    /*    Input must be a string                                    */
		/* ************************************************************ */
	    if ( mxIsChar(prhs[0]) != 1)
	      mexErrMsgTxt("Input must be a string.");

		/* ************************************************************ */
	    /*    Input must be a row vector                                */
		/* ************************************************************ */
	    if (mxGetM(prhs[0])!=1)
	      mexErrMsgTxt("Input must be a row vector.");
    
		/* ************************************************************ */
	    /*    Get the length of the input string                        */
		/* ************************************************************ */
	    buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;

		/* ************************************************************ */
	    /*    Allocate memory for input string                          */
		/* ************************************************************ */
	    input_buf=mxCalloc(buflen, sizeof(char));

		/* ************************************************************ */
	    /* Copy the string data from prhs[0] into a C string input_buf. */
		/* ************************************************************ */
	    status = mxGetString(prhs[0], input_buf, buflen);
	    if(status != 0) 
	      mexWarnMsgTxt("Not enough space. String is truncated.");
    
		/* ************************************************************ */
	    /*    Call the C subroutines to build the Project structure     */
		/* ************************************************************ */
		Read_DataMAX(input_buf);

		/* sleep( (clock_t)(5 * CLOCKS_PER_SEC)); */

		/* ******************************************************************** */
		/*                  Populate the MATLAB structure                       */
		/* ******************************************************************** */
		for (index = 0; index < Project.Test_Item.Run.Num_Chan; index++)
		{
			mxArray *Time_His_field_value;
			mxArray *Max_EU_field_value;
			mxArray *Max_Volts_field_value;
			mxArray *Sensitivity_field_value;
			mxArray *ChanNbr_field_value;
			mxArray *Module_field_value;

			/* ******************************************************************** */
			/*                   Populate Chan structure:                           */
			/* ******************************************************************** */
			Module_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Module);
			mxSetFieldByNumber(ChanStruct, index, Module_field, mxDuplicateArray(Module_field_value));

			ChanNbr_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].ChanNbr);
			mxSetFieldByNumber(ChanStruct, index, ChanNbr_field, mxDuplicateArray(ChanNbr_field_value));

			mxSetFieldByNumber(ChanStruct, index, Trans_Loc_field, mxCreateString(Project.Test_Item.Run.Channel[index].Trans_Loc));
			mxSetFieldByNumber(ChanStruct, index, Coordinate_field, mxCreateString(Project.Test_Item.Run.Channel[index].Coordinate));
			mxSetFieldByNumber(ChanStruct, index, Direction_field, mxCreateString(Project.Test_Item.Run.Channel[index].Direction));
			mxSetFieldByNumber(ChanStruct, index, Orientation_field, mxCreateString(Project.Test_Item.Run.Channel[index].Orientation));

			Sensitivity_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Sensitivity);
			mxSetFieldByNumber(ChanStruct, index, Sensitivity_field, mxDuplicateArray(Sensitivity_field_value));

			mxSetFieldByNumber(ChanStruct, index, EU_field, mxCreateString(Project.Test_Item.Run.Channel[index].EU));
			mxSetFieldByNumber(ChanStruct, index, Trans_Type_field, mxCreateString(Project.Test_Item.Run.Channel[index].Trans_Type));
			mxSetFieldByNumber(ChanStruct, index, Cable_Ext_field, mxCreateString(Project.Test_Item.Run.Channel[index].Cable_Ext));
			mxSetFieldByNumber(ChanStruct, index, Serial_Num_field, mxCreateString(Project.Test_Item.Run.Channel[index].Serial_Num));
			mxSetFieldByNumber(ChanStruct, index, Bypass_field, mxCreateString(Project.Test_Item.Run.Channel[index].Bypass));
			mxSetFieldByNumber(ChanStruct, index, Coupling_field, mxCreateString(Project.Test_Item.Run.Channel[index].Coupling));

			Max_Volts_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Max_Volts);
			mxSetFieldByNumber(ChanStruct, index, Max_Volts_field, mxDuplicateArray(Max_Volts_field_value));

			Max_EU_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Max_EU);
			mxSetFieldByNumber(ChanStruct, index, Max_EU_field, mxDuplicateArray(Max_EU_field_value));

			/* ************************************************************************************************** */
		    /*  Call the C subroutine to extract the time history data and insert it into the Project structure   */
			/* ************************************************************************************************** */
			/* Read_DataMAX(input_buf, index); */

			Time_His_field_value = mxCreateNumericMatrix(1, ChanLength, mxSINGLE_CLASS, mxREAL);
			Ptr = (unsigned char *) mxGetPr(Time_His_field_value);
			bytes_to_copy = ChanLength * mxGetElementSize(Time_His_field_value);
			memmove(Ptr, (Channel_Time_History + index * ChanLength), bytes_to_copy);

			mxSetFieldByNumber(ChanStruct, index, Time_His_field, mxDuplicateArray(Time_His_field_value));

			free(Project.Test_Item.Run.Channel[index].Time_His);

			mxDestroyArray(Time_His_field_value);
			mxDestroyArray(Max_EU_field_value);
			mxDestroyArray(Max_Volts_field_value);
			mxDestroyArray(Sensitivity_field_value);
			mxDestroyArray(ChanNbr_field_value);
			mxDestroyArray(Module_field_value);

		} /* end for (int index = 0; index < Num_Channels; index++) */
		/* ******************************************************************** */
		/*                     Populate Run structure:                          */
		/* ******************************************************************** */
		mxSetFieldByNumber(RunStruct, 0, Test_Date_field, mxCreateString(Project.Test_Item.Run.Test_Date));
		mxSetFieldByNumber(RunStruct, 0, Test_Type_field, mxCreateString(Project.Test_Item.Run.Test_Type));
		mxSetFieldByNumber(RunStruct, 0, Test_Level_field, mxCreateString(Project.Test_Item.Run.Test_Level));
		mxSetFieldByNumber(RunStruct, 0, Axis_field, mxCreateString(Project.Test_Item.Run.Axis));

		Time_Ref_field_value = mxCreateDoubleMatrix(1, ChanLength, mxREAL);
		Ptr = (unsigned char *) mxGetPr(Time_Ref_field_value);
		bytes_to_copy = ChanLength * mxGetElementSize(Time_Ref_field_value);
		memmove(Ptr, Project.Test_Item.Run.Time_Ref, bytes_to_copy);
		mxSetFieldByNumber(RunStruct, 0, Time_Ref_field, Time_Ref_field_value);

		mxFree(Project.Test_Item.Run.Time_Ref);

		Num_Chan_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(Num_Chan_field_value) = Project.Test_Item.Run.Num_Chan;
		mxSetFieldByNumber(RunStruct, 0, Num_Chan_field, Num_Chan_field_value);

		Sample_Rate_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(Sample_Rate_field_value) = Project.Test_Item.Run.Sample_Rate;
		mxSetFieldByNumber(RunStruct, 0, Sample_Rate_field, Sample_Rate_field_value);

		Low_Pass_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(Low_Pass_field_value) = Project.Test_Item.Run.Low_Pass;
		mxSetFieldByNumber(RunStruct, 0, Low_Pass_field, Low_Pass_field_value);
		mxSetFieldByNumber(RunStruct, 0, Setup_File_field, mxCreateString(Project.Test_Item.Run.Setup_File));
		mxSetFieldByNumber(RunStruct, 0, ADF_File_field,   mxCreateString(Project.Test_Item.Run.ADF_File));
		mxSetFieldByNumber(RunStruct, 0, Channel_field, ChanStruct);
		mxSetFieldByNumber(RunStruct, 0, Descrip_field, mxCreateString(Project.Test_Item.Run.Descrip));

		/* ******************************************************************** */
		/*                 Populate Test_Item structure:                        */
		/* ******************************************************************** */
		mxSetFieldByNumber(TestItemStruct, 0, TI_Name_field, mxCreateString(Project.Test_Item.Name));
		WD_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(WD_field_value) = Project.Test_Item.WD;
		mxSetFieldByNumber(TestItemStruct, 0, WD_field, WD_field_value);
		mxSetFieldByNumber(TestItemStruct, 0, Run_field, RunStruct);

		/* ******************************************************************** */
		/*                      Populate Project structure:                     */
		/* ******************************************************************** */
		mxSetFieldByNumber(plhs[0], 0, Name_field, mxCreateString(Project.Name));
		mxSetFieldByNumber(plhs[0], 0, Test_Item_field, TestItemStruct);

	} /* End of code block to populate the "C"-structure */

		/* ******************************************************************** */
		/*                Free memory allocated by mxCreate routines            */
		/* ******************************************************************** */
		/*
		mxDestroyArray(Num_Chan_field_value);
		mxDestroyArray(Low_Pass_field_value);
		mxDestroyArray(Module_field_value);
		mxDestroyArray(ChanNbr_field_value);
		mxDestroyArray(Sensitivity_field_value);
		mxDestroyArray(Max_Volts_field_value);
		mxDestroyArray(Max_EU_field_value);
		*/
}

